using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;

namespace Framework.Library.Core.Utils.Web.Modules
{
    public class DefaultResolveModule : IHttpModule
    {
        private const string DefaultPage = "default.aspx";
        private readonly object _lockObject = new object();
        private bool _resolveEventAttached;

        #region IHttpModule Members

        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += context_BeginRequest;
        }

        #endregion

        private void context_BeginRequest(object sender, EventArgs e)
        {
            if (!_resolveEventAttached)
            {
                lock (_lockObject)
                {
                    if (!_resolveEventAttached)
                    {
                        SiteMapProvider provider = SiteMap.Provider;

                        if (provider != null)
                            provider.SiteMapResolve += SiteMapResolve;

                        _resolveEventAttached = true;
                    }
                }
            }
        }

        private SiteMapNode SiteMapResolve(object sender, SiteMapResolveEventArgs e)
        {
            HttpContext context = e.Context;
            SiteMapProvider provider = e.Provider;

            if (context == null)
                return null;

            HttpRequest request = context.Request;
            string pageName = VirtualPathUtility.GetFileName(request.Path);

            if (string.Compare(pageName, DefaultPage, StringComparison.OrdinalIgnoreCase) == 0)
            {
                var resolveMethods = new List<SiteMapResolveEventHandler>();

                resolveMethods.Add(delegate { return provider.FindSiteMapNode(RemoveDefault(context.Request.RawUrl)); });

                resolveMethods.Add(delegate
                                       {
                                           int queryStartIndex = context.Request.RawUrl.IndexOf("?",
                                                                                                StringComparison.Ordinal);
                                           if (queryStartIndex != -1)
                                               return
                                                   provider.FindSiteMapNode(
                                                       RemoveDefault(context.Request.RawUrl.Substring(0, queryStartIndex)));
                                           else
                                               return null;
                                       });

                resolveMethods.Add(delegate
                                       {
                                           var page = context.CurrentHandler as Page;
                                           if (page != null)
                                           {
                                               string queryString = page.ClientQueryString;

                                               if (queryString.Length > 0)
                                                   return
                                                       provider.FindSiteMapNode(
                                                           RemoveDefault(context.Request.Path + "?" + queryString));
                                           }
                                           return null;
                                       });

                resolveMethods.Add(delegate { return provider.FindSiteMapNode(RemoveDefault(context.Request.Path)); });

                foreach (SiteMapResolveEventHandler method in resolveMethods)
                {
                    SiteMapNode node = method(sender, e);

                    if (node != null)
                        return node;
                }
            }

            return null;
        }

        public static string RemoveDefault(string url)
        {
            int startIndex = url.IndexOf(DefaultPage, StringComparison.OrdinalIgnoreCase);

            return (startIndex != -1) ? url.Remove(startIndex, DefaultPage.Length) : url;
        }
    }
}